/* Copyright 2024 Coremail
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
import { StringUtil } from '../utils/StringUtil';
import util from '@ohos.util';
import { FileManager } from '../utils/FileManger';
import { ExtVsMimeDict } from '../utils/MimeExtMap';

/**
 * manage the file path related to mail
 * 返回一个相对于系统文件夹的相对路径,完整路径需要加上 context.getDir();
 */
const IMPORTED_ACCOUNT:string = "imported"
const IMPORTED_MODULE:string = "mail_imported"
const Storage_MODULE:string = "mail_storage"
export class EmlFileManager {
  static base64Helper = new util.Base64Helper();
  /**
   * give a folder for every single mail.
   * **
   * 外部导入邮件的唯一标识符
   * @param account 邮件的账号,如果是外部导入的传null.
   * @param mailId 邮件id,如果是外部导入的,传文件的原始uri.
   * @param isInline 是否是内联图片.
   * 1,如果index不传,返回文件uri的hashcode作为标识符.
   * @returns
   *
   * 如果只传uri,返回该文件的hash值作为唯一名称.
   *
   * 如果传uri以及附件具体信息
   * 返回的名称需要加后缀.
   *
   * xxxxxxx.eml
   * xxxxxxx.msg
   * key = hash(mid);
   *    *    * accountKey = md5(account)
   *              mailKey = hash(mid);
   * /data/storage/el2/base/files/mail_db/MzA5NjAyMzkwQHFxLmNvbQ==/$key/eml/index.eml
   *
   *  远程下载的邮件
   *  maillDir: mail_db/$accountKey/$mailKey
   *  邮件:      mail_db/$accountKey/$mailKey/eml/index.eml
   *  内联附件:   mail_db/$accountKey/$mailKey/inline/$mailKey_$index.$ext
   *  外联附件:   mail_db/$accountKey/$mailKey/attach/$mailKey_$index.$ext
   *  正文:      mail_db/$accountKey/$mailKey/text/index.txt
   *  html:     mail_db/$accountKey/$mailKey/html/index.html
   *
   *  外部导入的邮件
   *  邮件:      mail_imported/imported/$mailKey/eml/$mid.eml
   *  内联附件:   mail_imported/imported/$mailKey/inline/$mailKey_$index.$ext
   *  外联附件:   mail_imported/imported/$mailKey/attach/$mailKey_$index.$ext
   *
   */
  static getRelativeDirPathForMail(account:string|null,mailId:string,folderFullName:string):string {
    let accountDir = EmlFileManager.getRelativeDirPathForAccount(account);
    let mailKey = this.getMailKey(mailId,folderFullName)
    return `${accountDir}/${mailKey}`
  }

  /**
   * 当前用户的file文件夹
   * @param account 如果没有account,表示是导入的.
   */
  static getRelativeDirPathForAccount(account:string):string {
    let module = (!account || account.length == 0) ? IMPORTED_MODULE : Storage_MODULE;
    let moduleDir = `${module}`
    let accountKey:string = EmlFileManager.base64Helper.encodeToStringSync(EmlFileManager.stringToUint8Array(account?account:IMPORTED_ACCOUNT))
    let accountDir = `${moduleDir}/${accountKey}`
    return accountDir;
  }
  /**
   * mailKey由mid和folderFullName组成的字符串hash得到.
   * 不同文件夹的mail可能会有相同的mid;
   * @param mid
   * @param folderFullName
   */
  static getMailKey(mid: string, folderFullName: string): string {
    return  `${StringUtil.hashCode(mid+folderFullName)}`
  }

  /**
   * 外部导入邮件 folderFullName传空字符串.
   * 获取eml源文所在的文件夹
   * @param account
   * @param mailId
   * @param folderFullName
   * @returns
   */
  static getRelativeDirPathForMailEml(account:string|null,mailId:string,folderFullName:string):string {
    let mailDir = EmlFileManager.getRelativeDirPathForMail(account,mailId,folderFullName);
    let emlPath = `${mailDir}/eml`
    return emlPath;
  }
  static getEmlNameForMail(mailId:string) : string {
    return "index.eml";
  }

  static getRelativeEmlPathForMail(account:string|null,mailId:string,folderFullName:string):string {
    let mailDir = EmlFileManager.getRelativeDirPathForMail(account,mailId,folderFullName);
    let emlName = this.getEmlNameForMail(mailId);
    let emlPath = `${mailDir}/eml/${emlName}`
    return emlPath;
  }
  /**
   * 返回邮件对应的正文文件的relativePath.
   * @param account
   * @param mailId
   * @returns
   */
  static getRelativeTextPathForMail(account:string|null,mailId:string,folderFullName:string):string {
    let mailDir = EmlFileManager.getRelativeDirPathForMail(account,mailId,folderFullName);
    let fileName = "index.txt";
    let filePath = `${mailDir}/text/${fileName}`
    return filePath;
  }
  /**
   * 返回邮件对应的html文件的relativePath.
   * @param account
   * @param mailId
   * @returns
   */
  static getRelativeHtmlPathForMail(account:string|null,mailId:string,folderFullName:string):string {
    let mailDir = EmlFileManager.getRelativeDirPathForMail(account,mailId,folderFullName);
    let fileName = "index.html";
    let filePath = `${mailDir}/html/${fileName}`
    return filePath;
  }


  /**
   * 
   * @param account
   * @param mailId
   * @param folderFullName
   * @param isInline
   * @returns
   */
  static getRelativeDirPathForMailAttachment(account:string|null,mailId:string,folderFullName:string, isInline:boolean):string {
    let mailDir = EmlFileManager.getRelativeDirPathForMail(account,mailId,folderFullName);
    let attachDirPath = `${mailDir}/${isInline?"inline":"attachment"}`
    return attachDirPath;
  }
  /**
   *
   * @param cid 内联图片传cid,attatchment传index.
   * @param mailId
   * @param isInline
   * @param rawName 原始文件名.
   * @returns
   */
  static getAttachNameWithRawName(cid:string,rawName:string,fileType:string):string {
    return StringUtil.uniqName(cid,rawName,fileType)
  }
  static getRelativeFilePathForMailAttachment(account:string|null,mailId:string,folderFullName:string,rawName:string,isInline:boolean,cid:string|null,fileType:string|null):string {
    let attachDirPath = EmlFileManager.getRelativeDirPathForMailAttachment(account,mailId,folderFullName,isInline);
    let fileName = this.getAttachNameWithRawName(cid,rawName,fileType);
    let attachPath = `${attachDirPath}/${fileName}}`
    return attachPath;
  }

  static stringToUint8Array(str: string):Uint8Array {
    let arr: number[] = [];
    for (let i = 0, j = str.length; i < j; ++i) {
      arr.push(str.charCodeAt(i));
    }
    let tmpUint8Array = new Uint8Array(arr);
    return tmpUint8Array
  }

}